package mp3player;

import java.io.IOException;
import java.io.InputStream;

import javazoom.jl.decoder.BitstreamException;

/**
 * An interface to handle both local and remote MP3 files/streams.
 */
public abstract class MP3 {
	/**
	 * Returns a string representation of this MP3 object.
	 */
	public String store() {
		if (this instanceof MP3File) {
			try {
				return "F"+((MP3File)this).getFile().getCanonicalPath();
			} catch (IOException ioe) { }
		} else if (this instanceof MP3Stream) {
			return "S"+((MP3Stream)this).getURL().toExternalForm();
		} else
			throw new RuntimeException("Unknown subclass:"+this.getClass());
		
		return null;
	}
	
	/**
	 * Converts a string representation returned by {@link #store()}
	 * to a suitable MP3File/MP3Stream object.
	 */
	public static MP3 load(String data) throws BitstreamException, IOException {
		if (data == null || data.length() < 1)
			return null;
		
		char type = data.charAt(0);
		if (type == 'F') {
			return new MP3File(data.substring(1));
		} else if (type == 'S') {
			return new MP3Stream(data.substring(1));
		}

		return null;
	}
	
	/**
	 * Opens a stream reading the contents of the MP3 file.
	 * @return A suitable stream object for reading.
	 */
	public abstract InputStream getStream() throws IOException;
	
	/**
	 * Returns a suitable title for the object.
	 */
	public abstract String getDisplayString();
	
	/**
	 * Returns the amount of frames in the MP3 file, if known.
	 * @return Number of frames in MP3, or 0 if unknown.
	 */
	public abstract int getFrames();
	
	/**
	 * Returns the total playing length of the MP3 file in
	 * milliseconds, if known.
	 * @return Playing length in ms, or 0.0f if unknown.
	 */
	public abstract float getLength();
	
	/**
	 * Returns <code>true</code> if the file is seekable.
	 */
	public abstract boolean isSeekable();
	
	/**
	 * Returns <code>true</code> if the file is a (potentially
	 * slow) stream.
	 */
	public abstract boolean isStream();
	
	/**
	 * Returns the frame index for the frame with an offset
	 * closest to <code>ms</code> milliseconds.
	 * @param ms Time in milliseconds from the beginning of the song.
	 * @return Frame index.
	 */
	public abstract int getClosestFrame(float ms);
	
	/**
	 * Converts the frame index to time offset.
	 * @param frame Frame number.
	 * @return Time from the beginning of the song, in milliseconds.
	 */
	public abstract float getFrameTime(int frame);

	/**
	 * Returns the name of the album.
	 * @return Name of the album, or <code>null</code> if not known.
	 */
	public abstract String getAlbum();
	/**
	 * Returns the name of the artist.
	 * @return Name of the artist, or <code>null</code> if not known.
	 */
	public abstract String getArtist();
	/**
	 * Returns the comment field contents.
	 * @return Comment contents or <code>null</code> if none.
	 */
	public abstract String getComment();
	/**
	 * Returns the genre of the content.
	 * @return Genre of the content, or <code>null</code> if not known.
	 */
	public abstract String getGenre();
	/**
	 * Returns the title of the song.
	 * @return Title of the song, or <code>null</code> if not known.
	 */
	public abstract String getTitle();
	/**
	 * Returns the track number on the album.
	 * @return Track number (between 1 and 31) or -1 if not applicable or unknown.
	 */
	public abstract int getTrack();
	/**
	 * Returns the publication year for the song.
	 * @return Publication year, or -1 if not known.
	 */
	public abstract int getYear();
}
